/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package clasificador.genetico.reglas;

import datos.AtributoFinito;
import datos.Dato;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import utils.Tuple;

/**
 *
 * @author e237573
 */
public class InterpretacionGenotipo<Clase> {

    public List<AtributoFinito> atributos;
    public AtributoFinito<Clase> clase;
    public Map<AtributoFinito, List> posiblesValores;

    public InterpretacionGenotipo(List<AtributoFinito> atributos, AtributoFinito clase) {
        this.atributos = atributos;
        this.clase = clase;

        this.posiblesValores = new HashMap<>();
        for (AtributoFinito a : atributos) {
            posiblesValores.put(a, a.getRango());
        }
    }

    private int log2(int k) {
        return 31 - Integer.numberOfLeadingZeros(k);
    }

    public Clase denormalizarClase(Integer clase) {
        List<Clase> clases = this.clase.getRango();
        int index = log2(clase);
        if (index < 0 || index >= clases.size()) {
            return null;
        } else {
            return clases.get(index);
        }
    }

    public Tuple<int[], Integer> normalizar(Dato d) {
        int indexClase = this.posiblesValores.get(this.clase).indexOf(d.getAtributo(this.clase));
        Integer valorClase = 1 << indexClase;
        return new Tuple<>(normalizarAtributos(d), valorClase);
    }

    public int[] normalizarAtributos(Dato d) {
        int[] valoresAtributos = new int[atributos.size()];
        int atributoActual = 0;

        for (AtributoFinito a : this.atributos) {
            if (!a.equals(this.clase)) {
                int index = this.posiblesValores.get(a).indexOf(d.getAtributo(a));
                valoresAtributos[atributoActual] = (1 << index);
                atributoActual++;
            }
        }
        return valoresAtributos;
    }    

    public Clase clasificar(TGenotipo i, int[] d) {
        /* MAJYCKS */
        clases:
        for (Tuple<int[], Integer> regla : i) {
            for (int atr = 0; atr < regla.l().length; atr++) {
                if (0 == (regla.l()[atr] & d[atr])) {
                    continue clases;
                }
            }
            return denormalizarClase(regla.r());
        }
        return null;
    }
}
